from .models import Structure, Tactic
import os, re
from bs4 import BeautifulSoup
from django.http import HttpResponse
from django.shortcuts import render
from .creeptest import add_Theory,update_from_doc_file
import socket
from .baidu_translate import get_a_text
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from itertools import chain
from . import creeptest
import datetime
import pytz
import time
from HOL4inWeb import password

def time_to_datetime(stamp):
    # dt = datetime.datetime.strptime(string , '%Y-%m-%d %H:%M:%S')
    # ts = int(dt.timestamp())
    ts = int(stamp)
    t = datetime.datetime.fromtimestamp(ts, pytz.timezone('Asia/Shanghai'))
    return t

def now():
    return time_to_datetime(time.time())


def add_errormsg_to_url(url, errormsg):
    if url.find('errormsg') > 0:
        if url[url.find('errormsg'):].find('&') > 0:
            url = url[:url.find('errormsg')] + 'errormsg=' + errormsg + url[url.find('errormsg'):][url[url.find('errormsg'):].find('&'):]
        else:
            url = url[:url.find('errormsg')] + 'errormsg=' + errormsg
    elif url.find('?') > 0:
        url = url + '&errormsg=' + errormsg
    else:
        url = url + '?errormsg=' + errormsg
    return url

def move_errormsg_in_url(url):
    if url.find('errormsg') > 0:
        if url[url.find('errormsg'):].find('&') > 0:
            url = url[:url.find('errormsg')] + url[url.find('errormsg'):][url[url.find('errormsg'):].find('&')+1:]
        else:
            url = url[:url.find('errormsg')-1]
    return url

# def get_a_text(url):
#     attributes = ['STRUCTURE', 'SYNOPSIS', 'DESCRIPTION', 'FAILURE', 'EXAMPLE', 'COMMENTS', 'USES', 'SEEALSO'][::-1]
#     soup = BeautifulSoup(open(url), "html.parser")
#     # b = re.sub(r'\s+', ' ', b)
#     try:
#         brkt = soup.find_all(class_='BRKT')
#         for br in brkt:
#             br.string = '%%*%s*%%'%br.text.replace('\n', '/n\\').replace(' ', '/b\\')
#         xmpl = soup.find_all(class_='XMPL')
#         for xm in xmpl:
#             xm.string = '{*%s*}'%xm.text.replace('\n', '/n\\').replace(' ', '/b\\')
#     except:
#         print('no brkt or xmpl:%s'%url)
#     b = re.sub('\s\s+', '\n', re.sub('\s', ' ', soup.body.dl.text)).replace('/n\\', '\n').replace('/b\\', ' ')
#     sortResult = {}
#     for x in attributes:
#         if b.find(x) > 0:
#             sortResult[x] = b[b.find(x)+len(x):].strip()
#             b = b[:b.find(x)]
#         else:
#             sortResult[x] = None
#     seealsoDir = {}
#     if sortResult['SEEALSO']:
#         href = soup.find_all(href=re.compile('.*'))
#         for hr in href:
#             if hr.text and hr.text in sortResult['SEEALSO']:
#                 seealsoDir[hr.text]=os.path.join(os.path.dirname(url), hr['href'])
#     sortResult['SEEALSO'] = seealsoDir
#     return sortResult

def find_file(path, filename):
    for root,dirs,files in os.walk(path):
        for name in files:
                if name == filename:
                        return (os.path.join(root, name))
    return ''

def update_a_tactical_text(name, stru):
    # tacticals = Structure.objects.filter(name='Tactical')
    tacs = Tactic.objects.filter(name=name, structure__name=stru)
    hostname = socket.gethostname()
    if tacs.exists():
        tac = tacs.first()
        try:
            if tac.url:
                if hostname == "LAPTOP-95UD5KNL":   #本地
                    url = tac.url[7:]
                if hostname == "iZj6cfxig0kxb4uqat81yqZ":   #服务器
                    url = tac.url[7:].replace('satone/', '')
            resu = update_from_doc_file("%s.%s"%(stru,name), password.DOCPATH)
            if resu == {}:
                resu = get_a_text(url)
                print("from html")
            if tac.synopsis and "No official synopsis." in tac.synopsis and resu == {}:
                return True
            tac.synopsis = resu['SYNOPSIS']
            tac.description = resu['DESCRIPTION']
            tac.failure = resu['FAILURE']
            tac.example = resu['EXAMPLE']
            tac.comments = resu['COMMENTS']
            tac.uses = resu['USES']
            tac.seealso = resu['SEEALSO']
            try:
                if tac.type == None or tac.type != resu['TYPE']:
                    tac.type = resu['TYPE']
            except:
                pass
            tac.updatetime = time_to_datetime(resu['DATATIME'])
            tac.save()
        except Exception as e:
            print("search.function.update_a_tactical_text error1: ",e)
    else:
        tac = Tactic()
        try:
            resu = update_from_doc_file("%s.%s"%(stru,name), path=password.DOCPATH)
            tac.synopsis = resu['SYNOPSIS']
            tac.description = resu['DESCRIPTION']
            tac.failure = resu['FAILURE']
            tac.example = resu['EXAMPLE']
            tac.comments = resu['COMMENTS']
            tac.uses = resu['USES']
            tac.seealso = resu['SEEALSO']
            oldStru = Structure.objects.filter(name=resu['STRUCTURE'])
            tac.name = resu['NAME']
            tac.url = resu['URL']
            if oldStru.exists():
                tac.structure = oldStru.first()
            else:
                newStru = Structure(name=resu['STRUCTURE'])
                newStru.url = os.path.join('/home/satone/HOL/help/src-sml/htmlsigs', resu['STRUCTURE'])+'.html'
                newStru.source = find_file(os.path.join(password.DOCPATH, '../../src'), resu['STRUCTURE']+'.sml')
                newStru.source = 'file://' + os.path.join('/home/satone',newStru.source[newStru.source.find('HOL/src'):]) 
                newStru.save()
                tac.structure = newStru
            try:
                if tac.type == None or tac.type != resu['TYPE']:
                    tac.type = resu['TYPE']
            except:
                pass
            tac.updatetime = time_to_datetime(resu['DATATIME'])
            tac.save()
        except Exception as e:
            print("search.function.update_a_tactical_text error2: ",e)
    return True

def add_tactical(structure=''):
    if structure:
        url = '/home/satone/HOL/help/src-sml/htmlsigs/' + structure + '.html'
        try:
            soup = BeautifulSoup(open(url), "html.parser")
        except:
            return False
        try:
            source = soup.table.a['href']
        except:
            source = ''
        if not Structure.objects.filter(name=structure).exists():
            stu = Structure(name=structure, url=url, source=source)
            stu.save()
        else:
            stu = Structure.objects.get(name=structure)
        try:
            pre = soup.find('pre')
            b = pre.text
            b = b.replace('\n', '  ')
            b = re.sub(r'\(\*.*?\*\)', '', b)
            b = re.sub(r'\s+->\s+', ' -> ', b)
        except:
            print ('!!error!!\nfilename:%s'%url)
            return False
        len1 = len(b)
        indexFix = 0
        for x in re.finditer(r'\{.*?\}', b):
            c = re.sub(r'\s+', ' ', b[x.span()[0]-indexFix:x.span()[1]-indexFix])
            b = b[:x.span()[0]-indexFix] + c + b[x.span()[1]-indexFix:]
            indexFix = len1 - len(b)
        # b = pre.text.replace('&gt;\n', '&gt;').replace('\n', '  ')
        # splitResult = []
        if b.find(' val ') > 0:
            try:
                # while b.find('(*') > 0:
                #     b = b[:b.find('(*')] + b[b.find('*)')+len('*)'):]
                b = b[b.find(' val '):]
                while b[5:].find(' val ') > 0:
                    t = b[:b[5:].find(' val ') + 5]
                    # splitResult.append({'name': t[5:t.find(':')].strip(), 'type': t[t.find(':')+1:].strip()})
                    if not Tactic.objects.filter(name=t[5:t.find(':')].strip(), structure=stu).exists():
                        if t.find('=') > 0 and t.find('=') < t.find(':'):
                            pass
                        else:
                            name = t[5:t.find(':')].strip()
                            ttype = t[t.find(':')+1:].lstrip()
                            if ttype.find(';') > 0 and ttype.find(';') < ttype.find('  '):
                                right = ttype.find(';')
                            else:
                                right = ttype.find('  ')
                            tac = Tactic(name=name, type=ttype[:right].rstrip(), structure=stu)
                            #print("save:%s"%name)
                            tac.save()
                    b = b[b[5:].find(' val ') + 5:]
                else:
                    t = b[:b.find('end')]
                    # splitResult.append({'name': t[5:t.find(':')].strip(), 'type': t[t.find(':')+1:].strip()})
                    if not Tactic.objects.filter(name=t[5:t.find(':')].strip(), structure=stu).exists():
                        if t.find('=') > 0 and t.find('=') < t.find(':'):
                            pass
                        else:
                            # tac = Tactic(name=t[5:t.find(':')].strip(), type=t[t.find(':')+1:t.find('  ')].strip(), structure=stu)
                            # tac.save()
                            name = t[5:t.find(':')].strip()
                            ttype = t[t.find(':')+1:].lstrip()
                            if ttype.find(';') > 0 and ttype.find(';') < ttype.find('  '):
                                right = ttype.find(';')
                            else:
                                right = ttype.find('  ')
                            tac = Tactic(name=name, type=ttype[:right].rstrip(), structure=stu)
                            #print("save:%s"%name)
                            tac.save()

                c = pre.find_all('a')
                for each in c:
                    try:
                        Tactic.objects.filter(name=each.text, structure=stu).update(url=each['href'])
                    except:
                        continue
                return True
            except:
                print ('!!error!!\nname:%s\ntype:%s\nstruture:%s'%(t[5:t.find(':')].strip(),t[t.find(':')+1:t.find('  ')].strip(),structure))
                return False
        else:
            return False

def add_all_tactical_to_DB(request):
    if request.method == 'POST':
        url = '/home/satone/HOL/help/HOLindex.html'
        soup = BeautifulSoup(open(url), "html.parser")
        splitResult = []
        t = soup.text.replace('\xa0','')
        t = t[t.find('STRUCTURES')+len('STRUCTURES'):t.find('SYNTAX')-1]
        while t.find('\n') > 0:
            splitResult.append(t[:t.find('\n')])
            t = t[t.find('\n')+1:]
        else:
            splitResult.append(t)
        falseList = []
        for s in splitResult:
            if not add_tactical(s.strip()): falseList.append(s)
        # add_tactical('Count')
        # srcpath = 'https://hol-theorem-prover.org/kananaskis-13-helpdocs/help/src-sml/htmlsigs/Tactic.html'
        return render(request, 'creeper.html', {'creepResult': falseList})
    return render(request, 'creeper.html',{'srcpath':'https://hol-theorem-prover.org/kananaskis-13-helpdocs/help/HOLindex.html'})

def add_htmlsigs_dir_thm_to_DB(request):
    path = '/home/satone/HOL/help/src-sml/htmlsigs/'
    filelist = os.listdir(path)
    falseList = []
    count = 0
    for s in filelist:
        if 'Theory' in s and s[-5:] == '.html':
            count += 1
            print(s[:-5])
            if not add_Theory(Structure, Tactic, s[:-5]): 
                #print(s)
                falseList.append(s)
    return HttpResponse(str(len(falseList)) + 'count：%s'%count)

def get_msg(request):
    ecode = request.GET.get('ecode', None)
    if ecode:
        if int(ecode) > 0:
            msg = settings.MSG_DIC[ecode]
            error_msg = None
        else:
            msg = None
            error_msg = settings.ERROR_DIC[ecode]
    else:
        msg = None
        error_msg = None
    return msg, error_msg

def send_email(email, code):

    subject = '来自holreference.top的注册确认邮件'

    text_content = '''欢迎注册holreference.top，这里是HOL4的参考资料搜索网站和社区，专注于HOL4定理证明器的学习和分享\
                        如果你看到这条消息，说明你的邮箱服务器不提供HTML链接功能，请联系管理员或更换注册邮箱！'''

    html_content = '''
                        <p>感谢注册<a href="http://{}/user/verify/?code={}" target=blank>www.holreference.top</a>，\
                        这里是HOL4的参考资料搜索网站和社区，专注于HOL4定理证明器的学习和分享</p>
                        <p>请点击站点链接完成邮箱确认！</p>
                        '''.format('www.holreference.top', code)

    msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")

    msg.send()

def send_reply_email(email, user, comment, link, time):
    subject = 'holreference.top 评论回复邮件通知'

    text_content = '''欢迎注册holreference.top，这里是HOL4的参考资料搜索网站和社区，专注于HOL4定理证明器的学习和分享\
                        如果你看到这条消息，说明你的邮箱服务器不提供HTML链接功能，请联系管理员或更换注册邮箱！'''

    html_content = '''
                        <p>用户：{}</p>
                        <p>内容：{}</p>
                        <p>链接：<a href="http://www.holreference.top/{}">http://www.holreference.top/{}</a></p>
                        <p>时间：{}</p>
                        '''.format(user, comment, link, link, time)
    
    msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")

    msg.send()

def reply_notification(reply):
    try:
        if reply.position.user.acceptemail != 0 and reply.user != reply.position.user:

            if reply.position.user.acceptemail == 3:
                if reply.__class__.__name__ == 'CommentsQuestion':
                    send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'community/question/?q=%s'%reply.position.id, reply.time)
                if reply.__class__.__name__ == 'ReplyQuestion':
                    send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'community/question/?q=%s'%reply.position.position.id, reply.time)
                if reply.__class__.__name__ == 'ReplyComment':
                    send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'tactic/?name=%s&stru=%s'%(reply.position.position.name, reply.position.position.structure.name), reply.time)

            if reply.position.user.acceptemail == 2 and reply.__class__.__name__ != 'ReplyQuestion':
                if reply.__class__.__name__ == 'CommentsQuestion':
                    send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'community/question/?q=%s'%reply.position.id, reply.time)
                if reply.__class__.__name__ == 'ReplyComment':
                    send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'tactic/?name=%s&stru=%s'%(reply.position.position.name, reply.position.position.structure.name), reply.time)

            if reply.position.user.acceptemail == 1 and reply.__class__.__name__ == 'CommentsQuestion':
                send_reply_email(reply.position.user.email, reply.user.name, reply.content, 'community/question/?q=%s'%reply.position.id, reply.time)
    except Exception as e:
        print("send reply email error:%s"%e)

def QuerysSet_sort(QuerysSet, sortList):
    try:
        resultSet = QuerysSet.none()
        for count,each in enumerate(sortList):
            resultSet = list(chain(resultSet, QuerysSet.filter(structure=each)))
            # print(resultSet, type(resultSet))
    except Exception as e:
        print("QuerysSet_sort ERROR:%s"%e)
    return resultSet


# X-Forwarded-For:简称XFF头，它代表客户端，也就是HTTP的请求端真实的IP，只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。
def get_ip(request):
    # '''获取请求者的IP信息'''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR',None)  # 判断是否使用代理
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]  # 使用代理获取真实的ip
    else:
        ip = request.META.get('REMOTE_ADDR')  # 未使用代理获取IP
        if not ip:
            ip = request.META.items()
            return str(ip)
    return ip

import http.client
import json
def query_ipaddress(ip):
    try:
        httpClient = http.client.HTTPConnection('freeapi.ipip.net')
        httpClient.request('GET', '/%s'%ip)
        response = httpClient.getresponse()
        result_all = response.read().decode("utf-8")
        result = json.loads(result_all)
    except Exception as e:
        result = ["error"]
    return result